Consider a service architecture such as the one shown in Figure 1. When you draw it out on the
whiteboard, you typically show the different “types” of boxes you use, and
if you have a small number, the individual boxes themselves. For example,
you might have a few “web frontend” boxes that host your web server, a few
“DB” boxes hosting your database, and so on.
Each of these “types” typically has the same kind of
code/software/bits running on that machine. All your web frontends
typically have the same web frontend code, all your database machines have
the same database software installed (with different partitions of data),
and all your backend mail servers probably run the same mail transfer
agent. This similarity is deliberate. If you want an extra web frontend,
you add one more machine with the right bits, and twiddle with the load
balancer to bring the new machine into rotation.
Windows Azure takes this informal grouping of machines that most
applications do and formalizes it into something called
roles. A Windows Azure role roughly corresponds
to a “type” of box. However, each role is tweaked for a special purpose.
There’s a web role that contains your website and frontend code.
There’s a worker role suited to background jobs and long-running
transactions.
Taking these core web and worker roles, Visual Studio offers a few
role templates that customizes them for specific
scenarios such as hosting a Windows Communication Foundation (WCF) service
or a FastCGI application. Table 1 lists the roles and
role templates offered by Windows Azure and what each of them is suited
for. You’ll see web and worker roles explored in detail later in this
chapter.
Table 1. Windows Azure role and role template types
Role type | Description |
---|
Web role | This is analogous to an
ASP.NET website hosted in IIS (which is, in fact, exactly how
Windows Azure hosts your code). This is your go-to option for
hosting websites, web services, and anything that needs to speak
HTTP, and can run on the IIS/ASP.NET stack. |
Worker role | A worker role in Windows
Azure fulfills the same role a long-running Windows service/cron
job/console application would do in the server world. You get to
write the equivalent of an int
main() that Windows Azure will call for you. You can put
absolutely any code you want in it. If you can’t fit your code in
any of the other role types, you can probably find a way to fit it
here. This is used for everything, including background jobs,
asynchronous processing, hosting application servers written in
non-.NET languages such as Java, or even databases such as
MySQL. |
CGI web role (web
role) | Windows Azure offers direct
support to host languages and runtimes that support the FastCGI
protocol. The CGI Role template
makes it easier for you. Though this is
offered as a first-class role type in Visual Studio, under the
covers it is just a web role with the CGI option turned
on. |
WCF service role (web
role) | This is another customized
version of the web role targeted at hosting WCF Services. Under
the covers, this is just a web role with some Visual Studio magic
to make it easier to write a WCF service. |
Though each role is targeted at a specific scenario, each can be
modified to fit a variety of scenarios. For example, the worker role can
act as a web server by listening on port 80. The web role can launch a
process to perform some long-running activity. You’ll have to resort to
tactics such as this to run code that isn’t natively part of the Microsoft
stack. For example, to run Tomcat (the popular Java application server),
you must modify the worker role to listen on the correct ports.
Service models in their current form in
Windows Azure are difficult to construct by hand. The “roles” are, in
reality, prepackaged service models. For example, a web role is a
service model component that specifies that the code should be hosted
inside IIS, should listen on port 80, and other magic bits to make
normal websites work. You get a few pregenerated service models with the SDK: one that
has the web role alone, one that has the worker role alone, and one that
contains both web and worker roles in various combinations. In the future, Windows Azure will have the capability to construct
more advanced service models directly. |
1. Role Instances
Let’s consider the boxes and arrows on the whiteboard. When you
draw out your architecture, you probably have more than one “type” of
box. Any site or service with serious usage is probably going to need
more than one web frontend. Just like the “type” of box corresponds to a
role in Windows Azure, the actual box corresponds to a role
instance.
Note the use of the terms type and
instance. The similarity to the same terms as used
in object-oriented programming (OOP) is deliberate. A role is similar to
a class/type in that it specifies the blueprint. However, the actual
code runs in a role instance, which is analogous to an instantiated
object.
Also note that there is a strict limitation of one role instance
per virtual machine; there is no concept of multiple roles on the
virtual machine. If you want to host more than one role on the same
virtual machine, you’ll need to pack the code together into a single web
role or worker role, and distribute the work yourself.
1.1. Role instances and the load balancer
In the boxes-and-diagrams version, how incoming traffic is
routed to your machines completely depends on your network setup. Your
infrastructure could have a mass of virtual local area networks
(VLANs), software and hardware load balancers, and various other
networking magic.
In Windows Azure, the relationship between role instances and
incoming traffic is simple. As shown earlier in Figure 4-1, all role instances for a role
are behind a load balancer. The load balancer distributes traffic in a
strict round-robin fashion to each role instance. For example, if you
have three web role instances, each will get one-third of the incoming
traffic. This even distribution is maintained when the number of
instances changes.
How does traffic directed toward
foo.cloudapp.net end up at a web role instance? A
request to a *.cloudapp.net URL is redirected
through DNS toward a virtual IP address
(VIP) in a Microsoft data center that your
service owns. This VIP is the external face for your service, and the
load balancer has the knowledge to route traffic hitting this VIP to
the various role instances.
Each of these role instances has its own special IP address that
is accessible only inside the data center. This is often called a
direct IP address (DIP).
Though you can’t get at these DIPs from outside the data center, these
are useful when you want roles to communicate with each other. Later
in this chapter, you’ll see the API that lets you discover what these
IP addresses are used for with the other role instances in your
service.
1.2. Controlling the number of instances
The number of role instances that your service uses is
specified in the service configuration (that is, the ServiceConfiguration.cscfg file). Under
each Role element, you should find
an Instances element that takes a
count parameter. That directly
controls the number of role instances your service uses. Since this is
part of the service configuration (and not the definition), this can
be updated separately, and doesn’t require rebuilding/redeploying your
package.
Example 1 shows a sample
service configuration with one instance. You can specify the instance
count separately for each role in your service.
Example 1. Sample service configuration
<?xml version="1.0"?> <ServiceConfiguration serviceName="CloudService1" xmlns= "http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceConfiguration"> <Role name="WebRole1"> <Instances count="1" /> <ConfigurationSettings /> </Role> </ServiceConfiguration>
|
Note that all instances in your role are identical. Later in
this chapter, you’ll see how to have roles on different virtual
machine sizes. It is currently not possible to have role instances of
the same role with different sizes.
Note: Today, there is a direct mapping between the number of role
instances and the number of virtual machines. If you ask for three
role instances, you’ll get three virtual machines. This also factors
into how your application gets billed. Remember that one of the
resources for which you are billed is the number of virtual machine
hours used. Every running role instance consumes one virtual machine
hour every hour. If you have three role instances, that is three
virtual machine hours every hour. Keep this in mind when changing
the instance count, because a typo could wind up as an expensive
mistake!
Though changing the number of role instances is simple in the
service configuration, it can take longer to update in the cloud than
other service configuration changes. The reason behind this is that
changing the instance count (or, to be specific, adding new instances)
means that new machines must be found to run your code. Depending on
the current state of the machine, some cleanup may be required before
your code can be run on the new machines. Take this into account when
making large changes to instance counts.
2. Role Size
Though this wasn’t available as part of the initial Windows Azure
release, the ability to specify the size of the virtual machine was
added in late 2009. To be specific, you get to choose how many “slices”
of the machine you want combined. Each size has a different billing
rate. As always, consult the Windows Azure website for up-to-date
information on the latest billing rates.
To specify the size for your role, use the vmsize attribute in the service definition file.
Since this is a service definition attribute, you cannot change this
dynamically without reuploading your package, or doing a service
upgrade.
Example 2 shows a sample
configuration file with the virtual machine size set to “extra large”
(the largest virtual machine size available). As of this writing, there
are four virtual machine sizes, ranging from Small to ExtraLarge.
Example 2. Virtual machine size
<?xml version="1.0" encoding="utf-8"?> <ServiceDefinition name="Test" xmlns= "http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition"> <WorkerRole name="Test" vmsize ="ExtraLarge"> <ConfigurationSettings/> </WorkerRole> </ServiceDefinition>
|
Table 2 lists all the
virtual machine sizes and their equivalent configuration if they were
real machines. This is meant to act as a rule of thumb to give you an
idea of the kind of performance you can expect. As you go from small to
large, you get a bigger slice of the CPU, RAM, and hard disk, as well as
I/O benefits. However, you should do performance and load testing with
your target workload before picking the virtual machine size on which
you want to run your code.
Table 2. Virtual machine reference sizes
Virtual machine
size | Reference machine
specifications |
---|
Small | One core, 1.75 GB RAM,
225 GB disk space |
Medium | Two cores, 3.5 GB RAM,
490 GB disk space |
Large | Four cores, 7.0 GB RAM,
1,000 GB disk space |
ExtraLarge | Eight cores, 14 GB RAM,
2,040 GB disk space |
Note: With the billing differences between virtual machine sizes, you
can test out various interesting configurations to see what works the
cheapest. This is especially true if your service doesn’t scale
strictly linearly as you add more role instances. For example, a
bigger virtual machine size might work out to be cheaper than having
multiple role instances while delivering equivalent performance, or
vice versa. Experiment with different sizes and numbers of instances
to determine how your service performs, and find the cheapest option
that works for you.